﻿//*** Guidance generated code ***//
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Linq;

namespace ProjectBase.Core
{
    /// <summary>
    ///     Extensions available on every place of the framework.
    /// </summary>
    public static partial class Ext
    {
        #region Nested type: Const
        public static class Const
        {
            /// <summary>
            ///     Contains "G" - date with time
            /// </summary>
            public const string G = "G";

            /// <summary>
            ///     Contains "d" - date only (without time)
            /// </summary>
            public const string D = "d";

            /// <summary>
            ///     Contains "N0" - number without decimals
            /// </summary>
            public const string N0 = "N0";

            /// <summary>
            ///     Contains "N2" - number with two decimals
            /// </summary>
            public const string N2 = "N2";
        }
        #endregion

        #region object IFormatProvider
        /// <summary>
        ///     Single access point to smarter 'ToDisplay()' method for ValueTypes and IPersistentObjects
        /// </summary>
        /// <param name = "value">ValueType</param>
        /// <param name = "formatOrNullTemplate">Value cannot be NULL! 1) if the object is decimal?, int?, short?, bool? or datetime? 
        ///     than provided string is used as the "format" and null template is set to string.Empty 
        ///     2) any other object uses provided string as the null alternative</param>
        /// <param name = "formatProvider"></param>
        /// <returns>string representing the value to be displayed based on currentCulture</returns>
        public static string ToDisplay<TSource>(this TSource value, string formatOrNullTemplate = null,
            IFormatProvider formatProvider = null)
        {
            if (value.Is())
            {
                // I. IPersistentObject 
                var persistent = value as IPersistentObject;
                if (persistent.Is())
                {
                    return persistent.ToDisplay();
                }

                // II. DateTime
                var dateTime = value as DateTime?;
                if (dateTime.Is())
                {
                    return ToDisplay(dateTime, formatOrNullTemplate, formatProvider);
                    // always is returned "formated" datetime
                }

                // III. integer
                var integerValue = value as int?;
                if (integerValue.Is())
                {
                    return ToDisplay(integerValue.Value, formatOrNullTemplate, formatProvider);
                }

                // IV. decimal
                var decimalValue = value as decimal?;
                if (decimalValue.Is())
                {
                    return ToDisplay(decimalValue.Value, formatOrNullTemplate, formatProvider);
                }

                // V. short
                var shortValue = value as short?;
                if (shortValue.Is())
                {
                    return ToDisplay(shortValue.Value, formatOrNullTemplate, formatProvider);
                }

                // VI. long
                var longValue = value as long?;
                if (longValue.Is())
                {
                    return ToDisplay(longValue.Value, formatOrNullTemplate, formatProvider);
                }

                // VII. bool
                var boolValue = value as bool?;
                if (boolValue.HasValue)
                {
                    return ToDisplay(boolValue.Value, formatProvider);
                }

                // VIII. double
                var doubleValue = value as double?;
                if (doubleValue.Is())
                {
                    return ToDisplay(doubleValue.Value, formatOrNullTemplate, formatProvider);
                }

                // IX. float
                var floatValue = value as float?;
                if (floatValue.Is())
                {
                    return ToDisplay(floatValue.Value, formatOrNullTemplate, formatProvider);
                }

                // X. Guid
                var guidValue = value as Guid?;
                if (guidValue.Is())
                {
                    return ToDisplay(guidValue.Value, formatOrNullTemplate, formatProvider);
                }

                // XI. ushort
                var ushortValue = value as ushort?;
                if (ushortValue.Is())
                {
                    return ToDisplay(ushortValue.Value, formatOrNullTemplate, formatProvider);
                }

                // XII. ulong
                var ulongValue = value as ulong?;
                if (ulongValue.Is())
                {
                    return ToDisplay(ulongValue.Value, formatOrNullTemplate, formatProvider);
                }

                // XIII. uint
                var uintValue = value as uint?;
                if (uintValue.Is())
                {
                    return ToDisplay(uintValue.Value, formatOrNullTemplate, formatProvider);
                }

                // XIV. byte
                var byteValue = value as byte?;
                if (byteValue.Is())
                {
                    return ToDisplay(byteValue.Value, formatOrNullTemplate, formatProvider);
                }

                // XV. sbyte
                var sbyteValue = value as sbyte?;
                if (sbyteValue.Is())
                {
                    return ToDisplay(sbyteValue.Value, formatOrNullTemplate, formatProvider);
                }

                return value.ToString();
            }
            return typeof(TSource).IsValueType
                       ? string.Empty
                       : formatOrNullTemplate ?? string.Empty;
        }
        #endregion object IFormatProvider

        #region int IFormatProvider
        /// <summary>
        ///     Provides ToDisplay() method with provided IFormatProvider and 'format' template
        ///     insetead of the null String.Empty is returned
        /// </summary>
        /// <param name = "value">any int? value to be converted to UI string</param>
        /// <param name = "format">int format (e.g. "N0"or thousands separated with to int places)</param>
        /// <param name = "formatProvider"></param>
        /// <returns>int? converted to string based on current culture</returns>
        public static string ToDisplay(int? value, string format = null, IFormatProvider formatProvider = null)
        {
            return value.HasValue
                       ? ToDisplay(value.Value, format, formatProvider)
                       : string.Empty;
        }

        /// <summary>
        ///     Provides ToDisplay() method with provided IFormatProvider and 'format' template
        /// </summary>
        /// <param name = "value">any int value to be converted to UI string</param>
        /// <param name = "format">int format (e.g. "N0"or thousands separated with to int places)</param>
        /// <param name = "formatProvider"></param>
        /// <returns>int converted to string based on current culture</returns>
        public static string ToDisplay(int value, string format = null, IFormatProvider formatProvider = null)
        {
            return format.IsEmpty() && formatProvider.Is()
                       ? value.ToString(formatProvider)
                       : value.ToString(format ?? Const.N0, formatProvider ?? CultureInfo.CurrentCulture);
        }
        #endregion int IFormatProvider

        #region uint IFormatProvider
        /// <summary>
        ///     Provides ToDisplay() method with provided IFormatProvider and 'format' template
        /// </summary>
        /// <param name = "value">any uint value to be converted to UI string</param>
        /// <param name = "format">uint format (e.g. "N0"or thousands separated with to uint places)</param>
        /// <param name = "formatProvider"></param>
        /// <returns>uint converted to string based on current culture</returns>
        internal static string ToDisplay(uint value, string format = null, IFormatProvider formatProvider = null)
        {
            return format.IsEmpty() && formatProvider.Is()
                       ? value.ToString(formatProvider)
                       : value.ToString(format ?? Const.N0, formatProvider ?? CultureInfo.CurrentCulture);
        }
        #endregion uint IFormatProvider

        #region short IFormatProvider
        /// <summary>
        ///     Provides ToDisplay() method with provided IFormatProvider and 'format' template
        ///     insetead of the null String.Empty is returned
        /// </summary>
        /// <param name = "value">any short? value to be converted to UI string</param>
        /// <param name = "format">short format (e.g. "N0"or thousands separated with to short places)</param>
        /// <param name = "formatProvider"></param>
        /// <returns>short? converted to string based on current culture</returns>
        public static string ToDisplay(short? value, string format = null, IFormatProvider formatProvider = null)
        {
            return value.HasValue
                       ? ToDisplay(value.Value, format, formatProvider)
                       : string.Empty;
        }

        /// <summary>
        ///     Provides ToDisplay() method with provided IFormatProvider and 'format' template
        /// </summary>
        /// <param name = "value">any short value to be converted to UI string</param>
        /// <param name = "format">short format (e.g. "N0"or thousands separated with to short places)</param>
        /// <param name = "formatProvider"></param>
        /// <returns>short converted to string based on current culture</returns>
        public static string ToDisplay(short value, string format = null, IFormatProvider formatProvider = null)
        {
            return format.IsEmpty() && formatProvider.Is()
                       ? value.ToString(formatProvider)
                       : value.ToString(format ?? Const.N0, formatProvider ?? CultureInfo.CurrentCulture);
        }
        #endregion short IFormatProvider

        #region ushort IFormatProvider
        /// <summary>
        ///     Provides ToDisplay() method with provided IFormatProvider and 'format' template
        /// </summary>
        /// <param name = "value">any ushort value to be converted to UI string</param>
        /// <param name = "format">ushort format (e.g. "N0"or thousands separated with to ushort places)</param>
        /// <param name = "formatProvider"></param>
        /// <returns>ushort converted to string based on current culture</returns>
        internal static string ToDisplay(ushort value, string format = null, IFormatProvider formatProvider = null)
        {
            return format.IsEmpty() && formatProvider.Is()
                       ? value.ToString(formatProvider)
                       : value.ToString(format ?? Const.N0, formatProvider ?? CultureInfo.CurrentCulture);
        }
        #endregion ushort IFormatProvider

        #region long IFormatProvider
        /// <summary>
        ///     Provides ToDisplay() method with provided IFormatProvider and 'format' template
        ///     insetead of the null String.Empty is returned
        /// </summary>
        /// <param name = "value">any long? value to be converted to UI string</param>
        /// <param name = "format">long format (e.g. "N0"or thousands separated with to long places)</param>
        /// <param name = "formatProvider"></param>
        /// <returns>long? converted to string based on current culture</returns>
        public static string ToDisplay(long? value, string format = null, IFormatProvider formatProvider = null)
        {
            return value.HasValue
                       ? ToDisplay(value.Value, format, formatProvider)
                       : string.Empty;
        }

        /// <summary>
        ///     Provides ToDisplay() method with provided IFormatProvider and 'format' template
        /// </summary>
        /// <param name = "value">any long value to be converted to UI string</param>
        /// <param name = "format">long format (e.g. "N0"or thousands separated with to long places)</param>
        /// <param name = "formatProvider"></param>
        /// <returns>long converted to string based on current culture</returns>
        public static string ToDisplay(long value, string format = null, IFormatProvider formatProvider = null)
        {
            if (format.IsEmpty()
                && formatProvider.Is())
            {
                return value.ToString(formatProvider);
            }
            return value.ToString(format ?? Const.N0, formatProvider ?? CultureInfo.CurrentCulture);
        }
        #endregion long IFormatProvider

        #region ulong IFormatProvider
        /// <summary>
        ///     Provides ToDisplay() method with provided IFormatProvider and 'format' template
        /// </summary>
        /// <param name = "value">any ulong value to be converted to UI string</param>
        /// <param name = "format">ulong format (e.g. "N0"or thousands separated with to ulong places)</param>
        /// <param name = "formatProvider"></param>
        /// <returns>ulong converted to string based on current culture</returns>
        internal static string ToDisplay(ulong value, string format = null, IFormatProvider formatProvider = null)
        {
            if (format.IsEmpty()
                && formatProvider.Is())
            {
                return value.ToString(formatProvider);
            }
            return value.ToString(format ?? Const.N0, formatProvider ?? CultureInfo.CurrentCulture);
        }
        #endregion ulong IFormatProvider

        #region decimal IFormatProvider
        /// <summary>
        ///     Provides ToDisplay() method with provided IFormatProvider and 'format' template
        ///     insetead of the null String.Empty is returned
        /// </summary>
        /// <param name = "value">any decimal? value to be converted to UI string</param>
        /// <param name = "format">decimal format (e.g. "N2"or thousands separated with to decimal places)</param>
        /// <param name = "formatProvider"></param>
        /// <returns>decimal? converted to string based on current culture</returns>
        public static string ToDisplay(decimal? value, string format = null, IFormatProvider formatProvider = null)
        {
            return value.HasValue
                       ? ToDisplay(value.Value, format, formatProvider)
                       : string.Empty;
        }

        /// <summary>
        ///     Provides ToDisplay() method with provided IFormatProvider and 'format' template
        /// </summary>
        /// <param name = "value">any decimal value to be converted to UI string</param>
        /// <param name = "format">decimal format (e.g. "N2"or thousands separated with to decimal places)</param>
        /// <param name = "formatProvider"></param>
        /// <returns>decimal converted to string based on current culture</returns>
        public static string ToDisplay(decimal value, string format = null, IFormatProvider formatProvider = null)
        {
            return format.IsEmpty() && formatProvider.Is()
                       ? value.ToString(formatProvider)
                       : value.ToString(format ?? Const.N2, formatProvider ?? CultureInfo.CurrentCulture);
        }
        #endregion decimal IFormatProvider

        #region double IFormatProvider
        /// <summary>
        ///     Provides ToDisplay() method with provided IFormatProvider and 'format' template
        ///     insetead of the null String.Empty is returned
        /// </summary>
        /// <param name = "value">any double? value to be converted to UI string</param>
        /// <param name = "format">double format (e.g. "N2"or thousands separated with to double places)</param>
        /// <param name = "formatProvider"></param>
        /// <returns>double? converted to string based on current culture</returns>
        public static string ToDisplay(double? value, string format = null, IFormatProvider formatProvider = null)
        {
            return value.HasValue
                       ? ToDisplay(value.Value, format, formatProvider)
                       : string.Empty;
        }

        /// <summary>
        ///     Provides ToDisplay() method with provided IFormatProvider and 'format' template
        /// </summary>
        /// <param name = "value">any double value to be converted to UI string</param>
        /// <param name = "format">double format (e.g. "N2"or thousands separated with to double places)</param>
        /// <param name = "formatProvider"></param>
        /// <returns>double converted to string based on current culture</returns>
        public static string ToDisplay(double value, string format = null, IFormatProvider formatProvider = null)
        {
            return format.IsEmpty() && formatProvider.Is()
                       ? value.ToString(formatProvider)
                       : value.ToString(format ?? Const.N2, formatProvider ?? CultureInfo.CurrentCulture);
        }
        #endregion double IFormatProvider

        #region float IFormatProvider
        /// <summary>
        ///     Provides ToDisplay() method with provided IFormatProvider and 'format' template
        ///     insetead of the null String.Empty is returned
        /// </summary>
        /// <param name = "value">any float? value to be converted to UI string</param>
        /// <param name = "format">float format (e.g. "N2"or thousands separated with to float places)</param>
        /// <param name = "formatProvider"></param>
        /// <returns>float? converted to string based on current culture</returns>
        public static string ToDisplay(float? value, string format = null, IFormatProvider formatProvider = null)
        {
            return value.HasValue
                       ? ToDisplay(value.Value, format, formatProvider)
                       : string.Empty;
        }

        /// <summary>
        ///     Provides ToDisplay() method with provided IFormatProvider and 'format' template
        /// </summary>
        /// <param name = "value">any float value to be converted to UI string</param>
        /// <param name = "format">float format (e.g. "N2"or thousands separated with to float places)</param>
        /// <param name = "formatProvider"></param>
        /// <returns>float converted to string based on current culture</returns>
        public static string ToDisplay(float value, string format = null, IFormatProvider formatProvider = null)
        {
            return format.IsEmpty() && formatProvider.Is()
                       ? value.ToString(formatProvider)
                       : value.ToString(format ?? Const.N2, formatProvider ?? CultureInfo.CurrentCulture);
        }
        #endregion float IFormatProvider

        #region Guid IFormatProvider
        /// <summary>
        ///     Provides ToDisplay() method with provided IFormatProvider and 'format' template
        ///     insetead of the null String.Empty is returned
        /// </summary>
        /// <param name = "value">any Guid? value to be converted to UI string</param>
        /// <param name = "format">Guid format (e.g. "N2"or thousands separated with to Guid places)</param>
        /// <param name = "formatProvider"></param>
        /// <returns>Guid? converted to string based on current culture</returns>
        public static string ToDisplay(Guid? value, string format = null, IFormatProvider formatProvider = null)
        {
            return value.HasValue
                       ? ToDisplay(value.Value, format, formatProvider)
                       : string.Empty;
        }

        /// <summary>
        ///     Provides ToDisplay() method with provided IFormatProvider and 'format' template
        /// </summary>
        /// <param name = "value">any Guid value to be converted to UI string</param>
        /// <param name = "format">Guid format (e.g. "N" result without dashes)</param>
        /// <param name = "formatProvider"></param>
        /// <returns>Guid converted to string based on current culture</returns>
        public static string ToDisplay(Guid value, string format = null, IFormatProvider formatProvider = null)
        {
            return format.IsEmpty() && formatProvider.Is()
                       ? value.ToString(Const.D, formatProvider)
                       : value.ToString(format ?? Const.D, formatProvider ?? CultureInfo.CurrentCulture);
        }
        #endregion Guid IFormatProvider

        #region DateTime IFormatProvider
        /// <summary>
        ///     Returns the string.Empty for null value
        ///     or DateTime value based on provided format string.
        ///     Null is converted to string.Empty
        /// </summary>
        /// <param name = "value"></param>
        /// <param name = "format"></param>
        /// <param name = "formatProvider"></param>
        /// <returns></returns>
        public static string ToDisplay(DateTime? value, string format = null, IFormatProvider formatProvider = null)
        {
            return value.HasValue
                       ? ToDisplay(value.Value, format, formatProvider)
                       : string.Empty;
        }

        /// <summary>
        ///     Returns the datetime value based on provided format string
        /// </summary>
        /// <param name = "value"></param>
        /// <param name = "format"></param>
        /// <param name = "formatProvider"></param>
        /// <returns></returns>
        public static string ToDisplay(DateTime value, string format = null, IFormatProvider formatProvider = null)
        {
            if (format.IsEmpty()
                && formatProvider.Is())
            {
                return value.ToString(formatProvider);
            }
            if (format.IsEmpty())
            {
                format = (value == value.Date)
                             ? Const.D // I. only date
                             : Const.G; // II. date and time
            }

            return format.IsEmpty()
                       ? value.ToString(formatProvider ?? CultureInfo.CurrentCulture)
                       : value.ToString(format, formatProvider ?? CultureInfo.CurrentCulture);
        }
        #endregion DateTime IFormatProvider

        #region bool IFormatProvider
        /// <summary>
        ///     Returns ToDisplay for Boolean?. If null then string.empty is returned
        /// </summary>
        /// <param name = "value"></param>
        /// <param name = "formatProvider"></param>
        /// <returns></returns>
        public static string ToDisplay(bool? value, IFormatProvider formatProvider = null)
        {
            return value.HasValue
                       ? ToDisplay(value.Value, formatProvider)
                       : string.Empty;
        }

        /// <summary>
        ///     Returns ToDisplay for Boolean?. If null then string.empty is returned
        /// </summary>
        /// <returns></returns>
        public static string ToDisplay(bool value, IFormatProvider formatProvider = null)
        {
            return value.ToString(formatProvider ?? CultureInfo.CurrentCulture);
        }
        #endregion bool IFormatProvider

        #region byte IFormatProvider
        /// <summary>
        ///     Provides ToDisplay() method with provided IFormatProvider and 'format' template
        ///     insetead of the null String.Empty is returned
        /// </summary>
        /// <param name = "value">any byte? value to be converted to UI string</param>
        /// <param name = "format">byte format (e.g. "N0"or thousands separated with to byte places)</param>
        /// <param name = "formatProvider"></param>
        /// <returns>byte? converted to string based on current culture</returns>
        public static string ToDisplay(byte? value, string format = null, IFormatProvider formatProvider = null)
        {
            return value.HasValue
                       ? ToDisplay(value.Value, format, formatProvider)
                       : string.Empty;
        }

        /// <summary>
        ///     Provides ToDisplay() method with provided IFormatProvider and 'format' template
        /// </summary>
        /// <param name = "value">any byte value to be converted to UI string</param>
        /// <param name = "format">byte format (e.g. "N0"or thousands separated with to byte places)</param>
        /// <param name = "formatProvider"></param>
        /// <returns>byte converted to string based on current culture</returns>
        public static string ToDisplay(byte value, string format = null, IFormatProvider formatProvider = null)
        {
            return format.IsEmpty() && formatProvider.Is()
                       ? value.ToString(formatProvider)
                       : value.ToString(format ?? Const.N0, formatProvider ?? CultureInfo.CurrentCulture);
        }
        #endregion byte IFormatProvider

        #region sbyte IFormatProvider
        /// <summary>
        ///     Provides ToDisplay() method with provided IFormatProvider and 'format' template
        /// </summary>
        /// <param name = "value">any sbyte value to be converted to UI string</param>
        /// <param name = "format">sbyte format (e.g. "N0"or thousands separated with to sbyte places)</param>
        /// <param name = "formatProvider"></param>
        /// <returns>sbyte converted to string based on current culture</returns>
        internal static string ToDisplay(sbyte value, string format = null, IFormatProvider formatProvider = null)
        {
            return format.IsEmpty() && formatProvider.Is()
                       ? value.ToString(formatProvider)
                       : value.ToString(format ?? Const.N0, formatProvider ?? CultureInfo.CurrentCulture);
        }
        #endregion sbyte IFormatProvider
    }
}